package downloader

import (
	"fmt"
	"net/url"
	"path"

	"github.com/pkg/sftp"
	"golang.org/x/crypto/ssh"
)

type SFTPDownloader struct {
	BaseDownloader
	client *sftp.Client
	ssh    *ssh.Client
}

func NewSFTPDownloader(config *Config) *SFTPDownloader {
	return &SFTPDownloader{
		BaseDownloader: BaseDownloader{
			config:   config,
			stopChan: make(chan struct{}),
		},
	}
}

func (d *SFTPDownloader) Download(urlStr string) error {
	u, err := url.Parse(urlStr)
	if err != nil {
		return fmt.Errorf("invalid URL: %w", err)
	}

	password, _ := u.User.Password()
	config := &ssh.ClientConfig{
		User: u.User.Username(),
		Auth: []ssh.AuthMethod{
			ssh.Password(password),
		},
		HostKeyCallback: ssh.InsecureIgnoreHostKey(),
	}

	d.ssh, err = ssh.Dial("tcp", u.Host, config)
	if err != nil {
		return fmt.Errorf("failed to connect to SSH: %w", err)
	}
	defer d.ssh.Close()

	d.client, err = sftp.NewClient(d.ssh)
	if err != nil {
		return fmt.Errorf("failed to create SFTP client: %w", err)
	}
	defer d.client.Close()

	src, err := d.client.Open(u.Path)
	if err != nil {
		return fmt.Errorf("failed to open remote file: %w", err)
	}
	defer src.Close()

	stat, err := src.Stat()
	if err != nil {
		return fmt.Errorf("failed to get file info: %w", err)
	}

	filename := path.Base(u.Path)
	d.initProgress(stat.Size(), filename)

	out, err := d.createOutputFile(filename)
	if err != nil {
		return err
	}
	defer out.Close()

	return d.copyWithProgress(out, src)
}

func (d *SFTPDownloader) Stop() error {
	if d.client != nil {
		d.client.Close()
	}
	if d.ssh != nil {
		d.ssh.Close()
	}
	close(d.stopChan)
	return nil
}

func (d *SFTPDownloader) Progress() float64 {
	d.mu.Lock()
	defer d.mu.Unlock()
	if d.totalSize == 0 {
		return 0
	}
	return float64(d.downloaded) / float64(d.totalSize) * 100
}

func (d *SFTPDownloader) Speed() int64 {
	return 0 // TODO: Implement speed calculation
}
